package com.jiuqian.demo.config;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.logging.Log4j2Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties("db")
public class DataSourceConfig {
	private String driverClassName;
	private int initialSize;
	private int maxActive;
	private int maxIdle;
	private int minIdle;
	private long maxWaitMillis;
	private long timeBetweenEvictionRunsMillis;
	private long minEvictableIdleTimeMillis;
	private int maxPoolPreparedStatementPerConnectionSize;
	private String url;
	private String username;
	private String password;
	@Value("${druid.filters}")
	private String filters;
	@Value("${druid.logType}")
	private String druidLogType;

	@Bean
	public StatFilter createStatFilter() {
		StatFilter statFilter = new StatFilter();
		long slowSqlMillis = 3000L;
		statFilter.setSlowSqlMillis(slowSqlMillis);
		statFilter.setLogSlowSql(true);
		statFilter.setMergeSql(true);
		return statFilter;
	}

	@Bean
	public Log4j2Filter createLog4j2Filter() {
		Log4j2Filter log4j2Filter = new Log4j2Filter();
		log4j2Filter.setDataSourceLogEnabled(true);
		log4j2Filter.setStatementExecutableSqlLogEnable(true);
		return log4j2Filter;
	}

	@PostConstruct
	private void initSystemProperty() {
		System.setProperty("druid.logType", this.druidLogType);
	}

	@Bean(destroyMethod = "close", initMethod = "init")
	public DataSource druidDataSource(StatFilter statFilter) throws SQLException {
		DruidDataSource datasource = new DruidDataSource();
		datasource.setUrl(this.url);
		datasource.setDriverClassName(this.driverClassName);
		datasource.setUsername(this.username);
		datasource.setPassword(this.password);
		datasource.setInitialSize(this.initialSize);
		datasource.setMinIdle(this.minIdle);
		datasource.setMaxWait(this.maxWaitMillis);
		datasource.setMaxActive(this.maxActive);
		datasource.setTimeBetweenEvictionRunsMillis(this.timeBetweenEvictionRunsMillis);
		datasource.setMinEvictableIdleTimeMillis(this.minEvictableIdleTimeMillis);
		datasource.setMaxPoolPreparedStatementPerConnectionSize(this.maxPoolPreparedStatementPerConnectionSize);

		List<Filter> proxyFilters = new ArrayList<Filter>();
		proxyFilters.add(statFilter);
		datasource.setProxyFilters(proxyFilters);

		datasource.setFilters(this.filters);
		datasource.setTestWhileIdle(true);
		datasource.setTestOnBorrow(true);
		datasource.setTestOnReturn(true);
		datasource.setValidationQuery("SELECT 'x'");
		datasource.setTimeBetweenLogStatsMillis(60000L);
		return datasource;
	}

	public String getDriverClassName() {
		return this.driverClassName;
	}

	public void setDriverClassName(String driverClassName) {
		this.driverClassName = driverClassName;
	}

	public int getInitialSize() {
		return this.initialSize;
	}

	public void setInitialSize(int initialSize) {
		this.initialSize = initialSize;
	}

	public int getMaxActive() {
		return this.maxActive;
	}

	public void setMaxActive(int maxActive) {
		this.maxActive = maxActive;
	}

	public int getMaxIdle() {
		return this.maxIdle;
	}

	public void setMaxIdle(int maxIdle) {
		this.maxIdle = maxIdle;
	}

	public int getMinIdle() {
		return this.minIdle;
	}

	public void setMinIdle(int minIdle) {
		this.minIdle = minIdle;
	}

	public long getMaxWaitMillis() {
		return this.maxWaitMillis;
	}

	public void setMaxWaitMillis(long maxWaitMillis) {
		this.maxWaitMillis = maxWaitMillis;
	}

	public long getTimeBetweenEvictionRunsMillis() {
		return this.timeBetweenEvictionRunsMillis;
	}

	public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
		this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
	}

	public long getMinEvictableIdleTimeMillis() {
		return this.minEvictableIdleTimeMillis;
	}

	public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
		this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
	}

	public int getMaxPoolPreparedStatementPerConnectionSize() {
		return this.maxPoolPreparedStatementPerConnectionSize;
	}

	public void setMaxPoolPreparedStatementPerConnectionSize(int maxPoolPreparedStatementPerConnectionSize) {
		this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;
	}

	public String getUrl() {
		return this.url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUsername() {
		return this.username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getFilters() {
		return this.filters;
	}

	public void setFilters(String filters) {
		this.filters = filters;
	}

	public String getDruidLogType() {
		return this.druidLogType;
	}

	public void setDruidLogType(String druidLogType) {
		this.druidLogType = druidLogType;
	}
}
